package com.jd.dlc.spi;

import com.jd.dlc.cache.access.AccessCache;
import com.jd.dlc.limit.Limiter;
import com.jd.dlc.spring.SpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;

import java.util.LinkedHashMap;

import static com.jd.dlc.spi.ExtensionLoader.EXTENSION_LOADER_CLASS_CACHE;

/**
 * @program: dlc
 * @ClassName SPIFactory
 * @description: Get SPI configuration
 * @author: sizegang
 **/
public class SPIFactory implements InitializingBean {

    Logger logger = LoggerFactory.getLogger(SPIFactory.class);

    private SPILoader spiLoader;

    public SPIFactory(SPILoader spiLoader) {
        this.spiLoader = spiLoader;
    }

    public <T> T getSPI(String key, Class clazz) {

        LinkedHashMap<String, Class> iRouterMap = EXTENSION_LOADER_CLASS_CACHE.get(clazz.getName());

        // SPI 获取到 负载均衡路由类
        Class iRouterClass = iRouterMap.get(key);

        /**
         * Take it from Spring first
         */
        Object bean = SpringUtils.getBean(iRouterClass.getSimpleName(), clazz);
        if (bean != null) {
            return (T) bean;
        }

        if (iRouterClass == null) {
            logger.error("SPI config is empty {}", key);
            return null;
        }
        try {
            return (T) iRouterClass.newInstance();
        } catch (Exception e) {
            return null;
        }
    }


    @Override
    public void afterPropertiesSet() {
        /**
         * cache breakdown SPI
         */
        spiLoader.initialize(AccessCache.class);
        spiLoader.initialize(Limiter.class);
    }
}
